home *** CD-ROM | disk | FTP | other *** search
- /* FILENAME: SWPLOGIC
- PURPOSE : To Provide Generic logic for The Minesweeper game
- As provided with WIN 3.1 */
- #include <values.h>
- #include "swplogic.h"
- #include <windows.h>
- #include <stdio.h>
- #include <windowsx.h>
- #include <mem.h>
- #include <time.h>
- #include <stdlib.h>
- #include <assert.h>
- #define STRICT
- #define ASDLL
- #ifdef ASDLL
- #define MAXGAMEHANDLES 10
- #else
- #define MAXGAMEHANDLES 1
- #endif
-
- #define MAXTIME 999
- char szDBG[128];
- typedef struct _gmElement_Tag
- { SHOWNTYPE sideShown; /* 0 = Top, 1 = Bottom */
- PIECEVAL Value ; /* 0..15 */
- BOOL Flagged;
- BOOL WrongGuess;
- }GMELEMENT, *PGMELEMENT, FAR *LPGMELEMENT;
- LPGMELEMENT *pTest;
-
-
- typedef struct _game_Tag
- {
- HSWP hswp;
- int nRows;
- int nCols;
- int nMines;
- HANDLE hGame;
- LPGMELEMENT *lpElements;
- HTASK hOwnerTask;
- GAMESTATE gmState;
- HWND hTimerWnd;
- WORD seconds;
- WORD wCorrectGuesses;
- WORD wGuesses;
- HWND hListener;
- }GAME, *PGAME, FAR *LPGAME;
-
- /* Local Declarations */
- GAME games[MAXGAMEHANDLES];
- void ShowAllUnFlaggedMines(LPGAME lpGamePtr);
- LOGICERR PlayNeighbours(LPGAME lpGamePtr,int I,int J);
- BOOL FlagCountMatches(LPGAME lp,int I,int J, int *);
- BOOL CheckFlagPositions(LPGAME lp,int I,int J);
- int RemoveGame(HSWP hswp);
- void ShowAllContiguousBlanks(LPGAME lpGamePtr,int I,int J,HWND hwnd);
- HSWP AddGame(int nRows, int nCols, int nMines,
- HWND hTimer,HTASK hOwner,LOGICERR *le);
- int InitGames(void);
- BOOL RandomizeGame(LPGAME lpGame);
- LPGAME GetGame(HSWP hswp);
- PIECEVAL CountNeighbors(LPGMELEMENT pGame[], int i,int j,int rowMax,int ColMax );
- int INBOUNDS(int row,int col,int rowMax,int colMax);
-
- HSWP FAR PASCAL _export logInitGame (int Rows,
- int Cols,
- int Mines,
- HWND hwndTimer,
- LOGICERR *logErr)
- { int i;
- HSWP hRetVal = NULL;
-
- if (Mines > Rows*Cols)
- *logErr = GMERR_TOOMANYMINES;
- else
- if (!IsWindow(hwndTimer))
- *logErr = GMERR_INVALIDHWND;
- else
- hRetVal = AddGame(Rows,Cols,Mines,hwndTimer,GetCurrentTask(),logErr);
- return hRetVal;
- }
-
-
- PIECEVAL FAR PASCAL _export logGetSideShown(HSWP hswp, int I, int J)
- {
- PIECEVAL pv;
- LPGAME lpGamePtr = NULL;
- lpGamePtr = GetGame(hswp);
- if (lpGamePtr == NULL)
- pv = PV_BADGAMEHANDLE;
- else{
- if (!INBOUNDS(I,J,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- pv = INVALID_PIECE;
- else{
- if ( (lpGamePtr->lpElements[I][J].sideShown ==TOP) &&
- (!lpGamePtr->lpElements[I][J].Flagged) ) {
- if (lpGamePtr->gmState != PLAYING && lpGamePtr->gmState != WAITING_AFTERRESET)
- return UP;
- else
- return NONE;
- }
- else
-
- if(lpGamePtr->lpElements[I][J].Flagged )
- return (UPFLAG);
- else
- return lpGamePtr->lpElements[I][J].Value;
- }
- }
- return pv;
- }
-
-
- LOGICERR FAR PASCAL logSetFlag(HSWP hswp, int I, int J)
- {
- LOGICERR le;
- LPGAME lpGamePtr = NULL;
- lpGamePtr = GetGame(hswp);
- if (lpGamePtr == NULL)
- le = GMERR_BADGAMEHANDLE;
- else
- {
- if (!INBOUNDS(I,J,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- le = GMERR_INDEXOUTOFRANGE;
- else
- {
- if (lpGamePtr->gmState != PLAYING &&
- lpGamePtr->gmState != WAITING_AFTERRESET)
- le = UNKNOWN;
- else
- if (lpGamePtr->lpElements[I][J].sideShown == TOP) {
- if (lpGamePtr->lpElements[I][J].Flagged) {
- lpGamePtr->wGuesses -= 1;
- lpGamePtr->lpElements[I][J].Flagged = FALSE;
- if (lpGamePtr->lpElements[I][J].Value == MINE)
- lpGamePtr->wCorrectGuesses -= 1;
-
- }else{
- lpGamePtr->wGuesses += 1;
- lpGamePtr->lpElements[I][J].Flagged = TRUE;
- if (lpGamePtr->lpElements[I][J].Value == MINE)
- lpGamePtr->wCorrectGuesses += 1;
- }
- le = GM_OK;
- }
- if (lpGamePtr->wCorrectGuesses == lpGamePtr->nMines)
- lpGamePtr->gmState = WON;
- }
- }
- return le;
- }
-
- WORD FAR PASCAL _export logGetMineCount(HSWP hswp)
- {
- LPGAME lpGamePtr = GetGame(hswp);
- if (lpGamePtr != NULL)
- {
- return (lpGamePtr->nMines - lpGamePtr->wGuesses);
- }
- else
- return MAXINT;
- }
-
- LOGICERR FAR PASCAL _export logPlay(HSWP hswp, int I, int J, BOOL isShifted)
- { int numFlags;
- int row,col;
- LPGAME lpGamePtr = NULL;
- LPGMELEMENT *lppGmElements;
-
- lpGamePtr = GetGame(hswp);
- if (!INBOUNDS(I,J,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- return -2;
-
- if (lpGamePtr == NULL)
- return GMERR_BADGAMEHANDLE;
-
- if((lpGamePtr->gmState != PLAYING) &&
- (lpGamePtr->gmState != WAITING_AFTERRESET))
- return GMERR_UNKNOWN;
-
- lppGmElements = lpGamePtr->lpElements;
- if (lppGmElements == NULL)
- return GMERR_MEMFAILURE;
-
- if ((lpGamePtr->gmState != WAITING_AFTERRESET )&&
- (lpGamePtr->gmState != PLAYING) &&
- (lpGamePtr->gmState != UNKNOWN) )
- return GMERR_UNKNOWN;
-
- if ( !INBOUNDS(I,J,lpGamePtr->nRows-1,lpGamePtr->nCols-1 ))
- return GMERR_INDEXOUTOFRANGE;
-
- if (lpGamePtr->gmState == WAITING_AFTERRESET ||
- lpGamePtr->gmState == UNKNOWN )
- lpGamePtr->gmState = PLAYING;
-
- if (isShifted)
- {
- if (FlagCountMatches(lpGamePtr,I,J,&numFlags))
- {
- OutputDebugString("FlagCountMatches\n");
- if (numFlags != 0)
- if (CheckFlagPositions(lpGamePtr,I,J)){
- return PlayNeighbours(lpGamePtr,I,J);
- }
- else{
- lpGamePtr->gmState = LOST;
- ShowAllUnFlaggedMines(lpGamePtr);
- return GMERR_LOST;
- }
- }
- else{
- OutputDebugString("FlagCount Did Not Match\n");
- return -45;
- }
- }
- if ( (lppGmElements[I][J].sideShown != TOP )||
- (lppGmElements[I][J].Flagged ))
- return GMERR_PIECEALREADYPLAYED;
-
- lppGmElements[I][J].sideShown = BOTTOM;
-
- if (lppGmElements[I][J].Value == MINE) {
- /* Change this so that value is never changed */
- //lppGmElements[I][J].Value = WRONGGUESS;
- lppGmElements[I][J].WrongGuess = TRUE;
- lpGamePtr->gmState = LOST;
- ShowAllUnFlaggedMines(lpGamePtr);
- return GMERR_LOST;
- }
-
- for (row = I-1; row <= I + 1; row++)
- for (col = J - 1; col <= J+1; col++)
- if (INBOUNDS(row,col,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- if (lppGmElements[row][col].sideShown == BOTTOM)
- if (CountNeighbors(lppGmElements,row,col,lpGamePtr->nRows-1,
- lpGamePtr->nCols-1) == NONE){
- ShowAllContiguousBlanks(lpGamePtr, row,col,lpGamePtr->hTimerWnd);
- return GM_MORETOPLAY ;
- }
- return GM_OK;
- }
-
- void ShowAllContiguousBlanks(LPGAME lpGamePtr,int I,int J,HWND hwnd)
- {
- int row,col;
- for (row = I-1; row <= I + 1; row++)
- for (col = J - 1; col <= J+1; col++)
- if (INBOUNDS(row,col,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- if ((lpGamePtr->lpElements[row][col].sideShown == TOP) &&
- (lpGamePtr->lpElements[row][col].Value != MINE)) {
-
- lpGamePtr->lpElements[row][col].sideShown = BOTTOM;
- SendMessage(lpGamePtr->hTimerWnd,WM_BLANKCELL,0,MAKELONG(row,col));
- if (lpGamePtr->lpElements[row][col].Value == NONE)
- ShowAllContiguousBlanks(lpGamePtr, row,col, hwnd);
- }
- }
-
- LOGICERR PlayNeighbours(LPGAME lp,int I,int J)
- {
- int row,col;
- LOGICERR retVal = GM_OK;
- if (INBOUNDS(I,J,lp->nRows-1,lp->nCols-1))
- for (row = I - 1; row <= I + 1; row++)
- for (col = J - 1; col <= J + 1; col++)
- if (!((row == I) && (col == J)))
- if (INBOUNDS(row,col,lp->nRows-1,lp->nCols-1))
- if (lp->lpElements[row][col].Flagged) {
- if (lp->lpElements[row][col].Value != MINE)
- {
- lp->lpElements[row][col].WrongGuess = TRUE;
- return GMERR_LOST;
- }
-
- }else
- if (lp->lpElements[row][col].sideShown == TOP){
- if (lp->lpElements[row][col].Value == MINE) {
- lp->lpElements[row][col].WrongGuess = TRUE;
- return GMERR_LOST;
- }
- else
- if (lp->lpElements[row][col].Value == NONE)
- ShowAllContiguousBlanks(lp, row,col,lp->hTimerWnd);
- else
- lp->lpElements[row][col].sideShown = BOTTOM;
-
- }
- return retVal;
- }
-
- void ShowAllUnFlaggedMines(LPGAME lpGamePtr)
- {
-
- int i, j;
- if (lpGamePtr != NULL){
- for (i = 0; i < lpGamePtr->nRows; i++)
- for (j = 0; j < lpGamePtr->nCols; j++)
- if ((lpGamePtr->lpElements[i][j].Value == MINE) &&
- (lpGamePtr->lpElements[i][j].sideShown == TOP ) &&
- (!lpGamePtr->lpElements[i][j].Flagged )){
- lpGamePtr->lpElements[i][j].sideShown = BOTTOM;
- PostMessage(lpGamePtr->hTimerWnd,WM_BLANKCELL,0,MAKELONG(i,j));
- }else
- if((lpGamePtr->lpElements[i][j].Value != MINE) &&
- (lpGamePtr->lpElements[i][j].Flagged ) ) {
- lpGamePtr->lpElements[i][j].sideShown = BOTTOM;
- lpGamePtr->lpElements[i][j].Value = ANOTHERWRONGGUESS;
- PostMessage(lpGamePtr->hTimerWnd,WM_BLANKCELL,0,MAKELONG(i,j));
- }
- }
- }
-
- PIECEVAL FAR PASCAL _export logGetValue(HSWP hswp, int I, int J)
- {
- PIECEVAL retPIECE;
- LPGMELEMENT *lppGmElements;
- LPGAME lpGamePtr = GetGame(hswp);
- if (lpGamePtr == NULL)
- return PV_BADGAMEHANDLE;
- if (lpGamePtr->lpElements == NULL)
- return PV_MEMFAILURE;
- lppGmElements = lpGamePtr->lpElements;
- if (!INBOUNDS(I,J,lpGamePtr->nRows-1,lpGamePtr->nCols-1))
- retPIECE = INVALID_PIECE;
- else
- if (lppGmElements[I][J].sideShown == TOP)
- {
- if (lppGmElements[I][J].Flagged)
- retPIECE = UPFLAG;
- else
- retPIECE = TOP;
- }else // This means we are returning the bottom value
- {
- if (lppGmElements[I][J].WrongGuess)
- retPIECE = WRONGGUESS;
- else
- retPIECE = lppGmElements[I][J].Value;
- }
- return retPIECE;
- }
-
- GAMESTATE FAR PASCAL _export logGetGameState(HSWP hswp)
- {
- LPGAME lpGamePtr;
- lpGamePtr = GetGame(hswp) ;
- if (lpGamePtr != NULL)
- return lpGamePtr->gmState;
- else
- return UNKNOWN;
- }
-
- LOGICERR FAR PASCAL _export logFreeGame(HSWP hswp)
- {
- if (GetGame(hswp) != NULL){
- if (RemoveGame(hswp))
- return GM_OK;
- else
- return GMERR_BADGAMEHANDLE;
- }else
- return GMERR_BADGAMEHANDLE;
- }
-
- LOGICERR FAR PASCAL _export logIncrementGameTime(HSWP hswp)
- {
- LOGICERR le;
- LPGAME lpGamePtr;
- lpGamePtr = GetGame(hswp) ;
- le = UNKNOWN;
- if (lpGamePtr == NULL)
- le = GMERR_BADGAMEHANDLE;
- else {
- if (lpGamePtr->seconds <= MAXTIME) {
- PostMessage(lpGamePtr->hTimerWnd,WM_SWEEPTIMER,lpGamePtr->seconds++,0L);
- le = GM_OK;
- }
- else {
- lpGamePtr->gmState = TIMEDOUT;
- le = GMERR_TIMEDOUT;
- }
- }
- return le;
- }
-
- #ifdef ASDLL
- #pragma argsused;
- int FAR PASCAL LibMain (HINSTANCE hInstance,
- WORD wDataSeg,
- WORD cbHeapSize,
- LPSTR lpCmdLine)
- {
- InitGames();
- return 1;
- }
- #pragma argsused
- int FAR PASCAL WEP (int nParameter)
- {
- int i;
- for (i = 0; i < MAXGAMEHANDLES; i++)
- RemoveGame(games[i].hswp);
- return 1;
- }
- #endif
- int
- RemoveGame(HSWP hswp)
- {
- LPGAME lpGamePtr;
- int retVal = -1;
- int j = 0;
- if (hswp == NULL)
- return 0;
-
- lpGamePtr = GetGame(hswp);
- if (lpGamePtr!=NULL) {
- for ( j = 0; j < lpGamePtr->nRows; j++)
- GlobalFreePtr(lpGamePtr->lpElements[j]);
-
- GlobalFreePtr(lpGamePtr->lpElements);
- lpGamePtr->hGame = NULL;
- lpGamePtr->nRows = 0;
- lpGamePtr->nCols = 0;
- lpGamePtr->hswp = NULL;
- lpGamePtr->gmState = UNKNOWN;
- lpGamePtr->nMines = 0;
- lpGamePtr->hTimerWnd = NULL;
- lpGamePtr->hOwnerTask= NULL;
- lpGamePtr->seconds = 0;
- retVal = 1;
- }
- return retVal;
- }
-
-
- HSWP
- AddGame(int nRows, int nCols, int nMines,
- HWND hTimerTo,HTASK hOwner,LOGICERR *le)
- {
- int j, k;
- int i = 0;
- *le = GM_OK;
- while ((i < MAXGAMEHANDLES ) && (games[i].hswp != NULL))
- ++i;
-
- if (i == MAXGAMEHANDLES) {
- *le = GMERR_TOOMANYGAMES;
- return NULL;
- }
- games[i].lpElements = (LPGMELEMENT*)GlobalAllocPtr(GMEM_SHARE|GMEM_ZEROINIT,
- (DWORD)sizeof(LPGMELEMENT)*nRows);
- if (games[i].lpElements == NULL) {
- *le = GMERR_MEMFAILURE;
- return NULL;
- }
- for (j = 0 ; j < nRows; j++) {
- games[i].lpElements[j] = (LPGMELEMENT)GlobalAllocPtr(GMEM_SHARE |
- GMEM_ZEROINIT,
- (DWORD)sizeof(GMELEMENT)*nCols);
- if (games[i].lpElements[j] == NULL) {
- assert(games[i].lpElements[j] != NULL);
- for (k = 0; k < j; k++)
- GlobalFreePtr(games[i].lpElements[k]);
- GlobalFreePtr(games[i].lpElements);
- *le = GMERR_MEMFAILURE;
- return NULL;
- }
- }
- games[i].hGame =(HANDLE)GlobalHandle(HIWORD(games[i].lpElements));
- games[i].nRows = nRows;
- games[i].nCols = nCols;
- games[i].hswp = games[i].hGame;
- games[i].gmState = WAITING_AFTERRESET;
- games[i].nMines = nMines;
- games[i].hTimerWnd = hTimerTo;
- games[i].hOwnerTask = hOwner;
- games[i].seconds = 0;
- games[i].wCorrectGuesses = 0;
-
- games[i].wGuesses = 0;
- games[i].hListener = NULL;
- if (!RandomizeGame(&games[i])) {
- *le = GMERR_UNKNOWN;
- RemoveGame(games[i].hswp);
- return NULL;
- }
- return games[i].hswp;
- }
-
-
- int
- InitGames(void)
- {
- int i;
- for (i = 0; i < MAXGAMEHANDLES; i++)
- games[i].hswp = NULL;
- return GM_OK;
- }
-
- BOOL
- RandomizeGame(LPGAME lpGamePtr)
- {
- BOOL retVal = FALSE;
- time_t t;
- int row,col;
- int mineCount = 0;
- if (lpGamePtr != NULL) {
- if (lpGamePtr->lpElements != NULL) {
- retVal = TRUE;
- /* Initialize the grid to having the Topside shown */
- /* Now Set the Values to NONE */
- for (row = 0; row < lpGamePtr->nRows; row++)
- for (col = 0; col < lpGamePtr->nCols; col++) {
- lpGamePtr->lpElements[row][col].WrongGuess = FALSE;
- lpGamePtr->lpElements[row][col].Flagged = FALSE;
- lpGamePtr->lpElements[row][col].Value = NONE;
- lpGamePtr->lpElements[row][col].sideShown = TOP;
- }
- /* Throw Mines down in random positions */
- /* Increment the Minecount only if the */
- /* position that is in question has not */
- /* been filled by a previous trip through*/
- /* the Loop */
- srand((unsigned) time(&t));
- while (mineCount < lpGamePtr->nMines){
- row = rand()%lpGamePtr->nRows;
- col = rand()%lpGamePtr->nCols;
- if (lpGamePtr->lpElements[row][col].Value != MINE) {
- mineCount++;
- lpGamePtr->lpElements[row][col].Value = MINE;
- }
- }
- /* Now Set the Neighbor mines for each field */
- for (row = 0; row < lpGamePtr->nRows; row++)
- for (col = 0; col < lpGamePtr->nCols; col++)
- if (lpGamePtr->lpElements[row][col].Value != MINE)
- lpGamePtr->lpElements[row][col].Value =
- CountNeighbors(lpGamePtr->lpElements,
- row,col,
- lpGamePtr->nRows - 1,
- lpGamePtr->nCols - 1);
- }
- }
- return retVal;
- }
-
- LPGAME
- GetGame(HSWP hswp)
- {
- int i;
- for (i = 0; i < MAXGAMEHANDLES; i++)
- if (games[i].hswp == hswp)
- return (&games[i]);
-
- return (LPGAME)NULL;
- }
-
- PIECEVAL CountNeighbors(LPGMELEMENT pGame[],
- int i, int j,
- int rowMax,int colMax )
- {
- PIECEVAL pV= NONE;
- int row,col;
- int nNeighborMineCount = 0;
-
- for (row = i - 1; row <= i + 1; row++)
- for (col = j - 1; col <= j + 1; col ++)
- if ((row == i)&&(col == j))
- continue;
- else
- if (INBOUNDS(row,col,rowMax,colMax) )
- if (pGame[row][col].Value == MINE)
- nNeighborMineCount++;
-
- switch (nNeighborMineCount) {
- case 0: pV = NONE ;break;
- case 1: pV = ONE ;break;
- case 2: pV = TWO ;break;
- case 3: pV = THREE;break;
- case 4: pV = FOUR ;break;
- case 5: pV = FIVE ;break;
- case 6: pV = SIX ;break;
- case 7: pV = SEVEN;break;
- case 8: pV = EIGHT;break;
- default: assert(pV != 0);
- }
- return pV;
- }
-
- BOOL FlagCountMatches(LPGAME lp,int I,int J,int *nFlags)
- {
- int row,col;
- int flagCount = 0;
- BOOL retVal = FALSE;
- if (INBOUNDS(I,J,lp->nRows-1,lp->nCols-1))
- for (row = I - 1; row <= I + 1; row++)
- for (col = J - 1; col <= J + 1; col++)
- if (!((row == I) && (col == J)))
- if (INBOUNDS(row,col,lp->nRows-1,lp->nCols-1))
- if (lp->lpElements[row][col].Flagged)
- ++flagCount;
-
- *nFlags = flagCount;
-
- switch (flagCount){
- case 0: if (lp->lpElements[I][J].Value == NONE ) retVal = TRUE;break;
- case 1: if (lp->lpElements[I][J].Value == ONE ) retVal = TRUE;break;
- case 2: if (lp->lpElements[I][J].Value == TWO ) retVal = TRUE;break;
- case 3: if (lp->lpElements[I][J].Value == THREE) retVal = TRUE;break;
- case 4: if (lp->lpElements[I][J].Value == FOUR ) retVal = TRUE;break;
- case 5: if (lp->lpElements[I][J].Value == FIVE ) retVal = TRUE;break;
- case 6: if (lp->lpElements[I][J].Value == SIX ) retVal = TRUE;break;
- case 7: if (lp->lpElements[I][J].Value == SEVEN) retVal = TRUE;break;
- case 8: if (lp->lpElements[I][J].Value == EIGHT) retVal = TRUE;break;
- }
- sprintf(szDBG,"The flagcount = %d RetVal = %d\n",flagCount,retVal);
- OutputDebugString(szDBG);
- return retVal;
- }
-
- BOOL CheckFlagPositions(LPGAME lp,int I,int J)
- {
- int row,col;
- if (INBOUNDS(I,J,lp->nRows-1,lp->nCols-1))
- for (row = I - 1; row <= I + 1; row++)
- for (col = J - 1; col <= J + 1; col++)
- if (!((row == I) && (col == J)))
- if (INBOUNDS(row,col,lp->nRows-1,lp->nCols-1))
- if (lp->lpElements[row][col].Flagged)
- if(lp->lpElements[row][col].Value != MINE)
- return FALSE;
- return TRUE;
- }
-
- int INBOUNDS(int row,int col,int rowMax,int colMax)
- {
- if ((row > rowMax) || (col > colMax) ||
- (row < 0 ) || (col < 0 ) )
- return 0;
- else
- return 1;
- }